# coding=utf-8

import traceback
import os
import random
from typing import Union, Iterable, NoReturn, Tuple, Any, Container
import unittest
from src import Public, logger
from src import pg
from src.exception.seleniumexecption import SeleniumTypeError
from src import Config
from src import db
from src import Compare


def _log_print(func):
	"""
	封装日志、控制台打印装饰器，用于断言
	:param func:
	:return:
	"""

	def wrapper(*args, **kwargs):
		# log_level = msg = None
		# print(args, kwargs)
		func_default_args = list(func.__defaults__)
		if Ellipsis == func_default_args[0]:
			func_default_args[0] = ""
		# func_name = func.__name__
		# if func_name in ["assertEqual", "assertNotEqual", "assertIn", "assertNotIn"]:
		msg = kwargs.get("msg") or (args[3] if len(args) > 3 else "") or (func_default_args[1])
		log_level = kwargs.get("log_level") or (args[4] if len(args) > 4 else "") or (func_default_args[0])

		try:
			func(*args, **kwargs)
		except Exception as e:
			if msg and log_level:
				eval(f"logger.{log_level.lower()}(msg=msg)")
				print(msg)
			raise AssertionError(e)

	return wrapper


class TestCaseMore(Public, unittest.TestCase):

	def shortDescription(self):
		doc_ret = super().shortDescription()
		doc = doc_ret if doc_ret else ""
		doc += self.describe
		return doc or None

	def screen_shot(self) -> NoReturn:
		"""
		说明：
			截图并会在测试报告中体现
			单独调试TestCase时，可以在“\Report\tempimg\”目录下查看截图
		"""
		s = traceback.extract_stack()
		project_dir = Config.project_dir
		random_int = random.randint(10000000, 99999999)  # 随机数
		# 图片名称 需要拼上测试案例相关信息
		screen_shot_name = (self.__module__
							+ "."
							+ self.__class__.__name__
							+ "."
							+ s[-2][2]
							+ "_"
							+ str(random_int)
							+ ".png")
		path = os.path.join(
			project_dir,
			"report",
			"tempimg",
			screen_shot_name,
		)
		# 截图保存
		self.driver.get_screen_shot(path=path)
		pg.SCREENSHOTS_NAME.append(screen_shot_name)

	def dbcheck(self, sql: Union[str, Iterable[str]]) -> bool:
		"""
		说明：
			执行数据比对

		:param sql: 需要比对的sql语句

		:return: True or False <class 'bool'>
		"""
		except_path, actual_path = self._get_compare_filename()
		except_exist = os.path.exists(except_path)
		if not except_exist:
			db.expectation(sql=sql,
						   excel_path=actual_path, )
			return False
		else:  # 存在期望结果则开始比较
			db.expectation(sql=sql,
						   excel_path=actual_path, )
			return Compare(expected=except_path, actual=actual_path).compare()

	def _get_compare_filename(self) -> Tuple[str, str]:
		_module = self.__module__
		_module = _module.replace(".", "/")
		case_filename = os.path.realpath(_module + ".py")
		_dir = os.path.dirname(case_filename)  # case案例所在目录
		_name = ("["
				 + self.__module__
				 + "."
				 + self.__class__.__name__
				 + "."
				 + self._testMethodName
				 + "]")
		except_path = os.path.join(_dir, _name) + "_[期望结果].xlsx"
		actual_path = os.path.join(_dir, _name) + "_[执行结果].xlsx"
		return except_path, actual_path

	@_log_print
	def assertEqual(self, first: Any, second: Any, msg: Any = ..., log_level="info") -> None:
		super().assertEqual(first=first, second=second, msg=msg)

	@_log_print
	def assertNotEqual(self, first: Any, second: Any, msg: Any = ..., log_level="info") -> None:
		super().assertNotEqual(first=first, second=second, msg=msg)

	@_log_print
	def assertIn(self, member: Any, container: Union[Iterable[Any], Container[Any]], msg: Any = ...,
				 log_level="info") -> None:
		super().assertIn(member=member, container=container, msg=msg)

	@_log_print
	def assertNotIn(self, member: Any, container: Union[Iterable[Any], Container[Any]], msg: Any = ...,
					log_level="info") -> None:
		super().assertNotIn(member=member, container=container, msg=msg)


if __name__ == '__main__':
	TestCaseMore().assertEqual(1, 2)
